package fpzhan.plane.program.compose;

import com.alibaba.fastjson.JSONObject;
import fpzhan.plane.program.function.CodeBlockFunction;
import fpzhan.plane.program.proxy.CodeBlockProxy;
import fpzhan.plane.program.struct.CodeBlockStruct;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;


public abstract class CodeBlockCompose implements Serializable {





    private ComposeContext composeContext =new ComposeContext();

    public abstract CodeBlockFunction compose(
            List<CodeBlockProxy> proxys,
            JSONObject proxyJson,
            CodeBlockStruct struct,
            JSONObject structJson,
            ComposeContent composeContent
    ) throws Exception;


    protected     CodeBlockFunction compose(
            List<CodeBlockProxy> proxys,
            JSONObject proxyJson,
            CodeBlockStruct struct,
            JSONObject structJson,
            ComposeContent composeContent,
             CodeBlockFunction codeBlock
    ) throws Exception {
        CodeBlockFunction compose=null;
        if (proxys!=null && proxys.size()>0){
            Collections.sort(proxys);
            compose=param -> {
                Map<CodeBlockProxy,JSONObject> beforeJson = new HashMap<>();
                for (CodeBlockProxy proxy:proxys){
                    beforeJson.put(proxy,proxy.before(composeContext,composeContent,new HashSet(param.keySet()),proxyJson));
                }
                try {
                    codeBlock.apply(param);
                }catch (Exception e){
                    if(e.getMessage()!=null && e.getMessage().contains("步骤:")){
                        throw e;
                    }
                   throw  new Exception("步骤:"+ composeContext.getComment(),e);
                }

                for (CodeBlockProxy proxy:proxys){
                    proxy.after(beforeJson.get(proxy), composeContext,composeContent,new HashSet(param.keySet()),proxyJson);
                }
            };
        }else{
            compose=codeBlock;
        }
        if (struct!=null){
            structJson=struct.struct(composeContext,composeContent,structJson);
        }
        return compose;
    }

    public CodeBlockCompose( ) {}

    public CodeBlockCompose(ComposeContext composeContext) {
        this.composeContext = composeContext;
    }

    public ComposeContext getComposeContext() {
        return composeContext;
    }



    public void setLoses(String[] loses) {
        composeContext.setLoses(loses);
    }



    public void setAdds(String[] adds) {
        composeContext.setAdds(adds);
    }



    public void setComposeType(String composeType) {
        composeContext.setComposeType(composeType);
    }
}
